%****************************************************************************%
%* DIET User's Manual server chapter file                                   *%
%*                                                                          *%
%*  Author(s):                                                              *%
%*    - Eddy CARON (Eddy.Caron@ens-lyon.fr)                                 *%
%*    - Philippe COMBES (Philippe.Combes@ens-lyon.fr)                       *%
%*    - Georg Hoesh (Georg.Hoesh@ens-lyon.fr)                               *%
%*                                                                          *%
%* $LICENSE$                                                                *%
%****************************************************************************%
%* $Id: server.tex,v 1.18 2008/07/02 10:04:17 bdepardo Exp $
%* $Log: server.tex,v $
%* Revision 1.18  2008/07/02 10:04:17  bdepardo
%* Proofreading of chapters 5 and 7.
%*
%* Revision 1.17  2006/11/29 16:55:11  dloureir
%* minor corrections
%*
%* Revision 1.16  2006/11/15 22:36:50  eboix
%*   Documentation concerning user compilation updated. --- Injay2461
%*
%* Revision 1.15  2006/09/11 11:15:00  ycaniou
%* - Up to date documentation for parallel/batch submission
%* - Corrected wrong references
%*
%* Revision 1.14  2006/06/06 09:05:30  eboix
%* FIX. --- Injay2461
%*
%* Revision 1.13  2006/01/25 16:52:55  pfrauenk
%* CoRI : renaming of the chapter performance prediction with fast
%* 	to performance prediction, add of the CoRI Usersmanual,
%* 	changes in the plugin scheduler
%*
%* Revision 1.12  2005/06/27 08:59:41  hdail
%* Updating interfaces to agree with current versions and adding memory cleanup
%* to end of example programs.
%*
%* Revision 1.11  2005/05/29 13:51:22  ycaniou
%* Moved the section concerning FAST from description to a new chapter about FAST
%* and performances prediction.
%* Moved the section about convertors in the FAST chapter.
%* Modified the small introduction in chapter 1.
%* The rest of the changes are purely in the format of .tex files.
%*
%* Revision 1.10  2004/07/12 13:26:11  mcolin
%* Correct the first example service/solve_service : pb of pointer.
%* There is still a pb with diet_string_get (it exists?) and with
%* parameter 3 (is this an OUT or INOUT parameter and so
%* must we use diet_desc_set?)
%*
%* Revision 1.9  2004/07/08 15:59:10  mcolin
%* correct the asynchronous example from the tutorial and user manual
%* FIXME :
%*  - still a bug with the INOUT parameter : the matrix is not modified
%*  - User Manuel [5.1] : the first example service/solve_service doesn't
%*  match with the actual version of DIET (pb with pointer and diet_string_get
%*  which doesn't exist)
%*
%* Revision 1.8  2004/02/10 01:12:16  ecaron
%* Add suggestions from Jean-Yves L'Excellent. Thanks !
%*
%* Revision 1.7  2004/01/29 17:08:47  ecaron
%* Add suggestions from Frederic Desprez. Thanks !
%*
%* Revision 1.5  2004/01/21 00:25:13  ecaron
%* Add suggestions from Holly Dail. Thanks !
%*
%* Revision 1.4  2004/01/05 23:17:00  ecaron
%* Building a server application for DIET 1.0
%****************************************************************************%

\chapter{Building a server application}
\label{ch:server}

A DIET server program is the link between the DIET Server Deamon
(SeD) and the libraries that implement the service to offer.

\section{Structure of the program}
\label{sec:sv_struct}

As for the client side, the DIET SeD is a library. So the server
developer needs to define the \texttt{main} function. Within the
\texttt{main}, the DIET server will be launched with a call to
\texttt{diet\_SeD} which will never return (except if some errors
occur). The complete server side interface is described in the files
\texttt{DIET\_data.h} (see Chapter~\ref{ch:data}) and \texttt{DIET\_server.h}
found in \texttt{$<$install\_dir$>$/include}. Do not forget to
include the \texttt{DIET\_server.h} (\texttt{DIET\_server.h}
includes \texttt{DIET\_data.h}) at the beginning of your server
source code.

{\footnotesize
\begin{verbatim}
#include <stdio.h>
#include <stdlib.h>

#include "DIET_server.h"
\end{verbatim}
}

The second step is to define a function whose prototype is ``DIET-normalized''
and which will be able to convert the function into the library function prototype.
Let us consider a library function with the following prototype:
{\footnotesize
\begin{verbatim}
int service(int arg1, char *arg2, double *arg3);
\end{verbatim}
}

This function cannot be called directly by DIET, since such a prototype is hard
to manipulate dynamically. The user must define a ``solve'' function whose
prototype only consists of a \texttt{diet\_profile\_t}.
This function will be called by the DIET SeD through a pointer.
{\footnotesize
\begin{verbatim}
int solve_service(diet_profile_t *pb)
{
   int    *arg1;
   char   *arg2;
   double *arg3;

   diet_scalar_get(diet_parameter(pb,0), &arg1, NULL);
   diet_string_get(diet_parameter(pb,1), &arg2, NULL);
   diet_scalar_get(diet_parameter(pb,2), &arg3, NULL);
   return service(*arg1, arg2, arg3);
}
\end{verbatim}
}

Several API functions help the user to write this ``solve''
function, particularly for getting IN arguments as well as setting
OUT arguments.

\subsubsection*{Getting IN, INOUT and OUT arguments}

The \texttt{diet\_*\_get} functions defined in \texttt{DIET\_data.h} are still
usable here. Do not forget that the necessary memory space for OUT arguments is
allocated by DIET. So the user should call the \texttt{diet\_*\_get} functions
to retrieve the pointer to the zone his/her program should write to.

\subsubsection*{Setting INOUT and OUT arguments}

To set INOUT and OUT arguments, use the \texttt{diet\_*\_desc\_set} defined
in \texttt{DIET\_server.h}, these are helpful for writing ``solve''
functions only. Using these functions, the server developer must keep in
mind the fact that he cannot alter the memory space pointed to by
value fields on the server. Indeed, this would make DIET confused
about how to manage the data{\footnote{And the server developer
should not be confused by the fact that
\texttt{diet\_scalar\_desc\_set} uses a value, since scalar values
are copied into the data descriptor.}}.

{\footnotesize
\begin{verbatim}
/**
 * If value                 is NULL,
 * or if order              is DIET_MATRIX_ORDER_COUNT,
 * or if nb_rows or nb_cols is 0,
 * or if path               is NULL,
 * then the corresponding field is not modified.
 */

int
diet_scalar_desc_set(diet_data_t* data, void* value);

// No use of diet_vector_desc_set: size should not be altered by server

// You can alter nb_r and nb_c, but the total size must remain the same
int
diet_matrix_desc_set(diet_data_t* data,
                     size_t nb_r, size_t nb_c, diet_matrix_order_t order);

// No use of diet_string_desc_set: length should not be altered by server

int
diet_file_desc_set(diet_data_t* data, char* path);
\end{verbatim}
}


\section{Server API}
\label{sec:svAPI}


\subsubsection*{Defining services}

First, declare the service(s) that will be offered{\footnote{It is
possible to declare several services for one single SeD.}}.
Each service is described by a profile description called
\texttt{diet\_profile\_desc\_t} since the service does not specify
the sizes of the data. The \texttt{diet\_profile\_desc\_t} type is
defined in \texttt{DIET\_server.h}, and is very similar to
\texttt{diet\_profile\_t}. The difference is that the prototype is
described with the generic parts of \emph{diet\_data\_desc} only,
whereas the client description uses full \emph{diet\_data}.
{\footnotesize
\begin{verbatim}
file DIET_data.h:
     struct diet_data_generic {
       diet_data_type_t type;
       diet_base_type_t base_type;
     };

file DIET_server.h:
     typedef struct diet_data_generic diet_arg_desc_t;

     typedef struct {
       char*            path;
       int              last_in, last_inout, last_out;
       diet_arg_desc_t* param_desc;
     } diet_profile_desc_t;

diet_profile_desc_t* diet_profile_desc_alloc(const char* path,
                        int last_in, int last_inout, int last_out);
int diet_profile_desc_free(diet_profile_desc_t* desc);

diet_profile_desc_t *diet_profile_desc_alloc(int last_in, int last_inout, int last_out);

int diet_profile_desc_free(diet_profile_desc_t *desc);
\end{verbatim}
}

Each profile can be allocated with \texttt{diet\_profile\_desc\_alloc} with the
same semantics as for \texttt{diet\_profile\_alloc}. Every argument of the
profile will then be set with \texttt{diet\_generic\_desc\_set} defined in
\texttt{DIET\_server.h}.

\subsubsection*{Declaring services}

Every service must be added in the service table before the server is
launched. The complete service table API is defined in \texttt{DIET\_server.h}:
{\footnotesize
\begin{verbatim}
typedef int (* diet_solve_t)(diet_profile_t *);
int diet_service_table_init(int max_size);
int diet_service_table_add(diet_profile_desc_t *profile,
                           diet_convertor_t    *cvt,
                           diet_solve_t         solve_func);
void diet_print_service_table();
\end{verbatim}
}

The parameter \texttt{diet\_solve\_t solve\_func} is the type of the
\texttt{solve\_service} function: a function pointer used by DIET to launch the
computation.

The parameter \texttt{diet\_convertor\_t *cvt} is to be used in combination
with FAST (if available). It is there to allow profile conversion (for
multiple services, or when differences occur between the DIET and the FAST
profile). Profile conversion is complicated and will be treated
separately in Chapter~\ref{chapter:performance}.

\section{Example}
\label{sec:sv_ex}

Let us consider the same example as in Chapter \ref{ch:client}, where
a function \texttt{scal\_mat\_prod} performs the product of a matrix
and a scalar and returns the time required for the computation: {\footnotesize
\begin{verbatim}
int scal_mat_prod(double alpha, double *M, int nb_rows, int nb_cols, float *time);
\end{verbatim}
}
Our program will first define the solve function that consists of the link
between DIET and this function. Then, the \texttt{main} function defines one service and
adds it in the service table with its associated solve function.
{\footnotesize
\begin{verbatim}
#include "DIET_server.h"
#include "scal_mat_prod.h"

int solve_smprod(diet_profile_t *pb)
{
  double *alpha;
  double *M;
  float  time;
  size_t m, n;
  int res;

  /* Get arguments */
  diet_scalar_get(diet_parameter(pb,0), &alpha, NULL);
  diet_matrix_get(diet_parameter(pb,1), &M, NULL, &m, &n, NULL);
  /* Launch computation */
  res = scal_mat_prod(*alpha, M, m, n, &time);
  /* Set OUT arguments */
  diet_scalar_desc_set(diet_parameter(pb,2), &time);
  /* Free IN data */
  diet_free_data(diet_parameter(pb,0));

  return res;
}

int main(int argc, char* argv[])
{
  diet_profile_desc_t *profile;
  
  /* Initialize table with maximum 1 service */
  diet_service_table_init(1);
  /* Define smprod profile */
  profile = diet_profile_desc_alloc("smprod",0, 1, 2);
  diet_generic_desc_set(diet_param_desc(profile,0), DIET_SCALAR, DIET_DOUBLE);
  diet_generic_desc_set(diet_param_desc(profile,1), DIET_MATRIX, DIET_DOUBLE);
  diet_generic_desc_set(diet_param_desc(profile,2), DIET_SCALAR, DIET_FLOAT);
  /* Add the service (the profile descriptor is deep copied) */
  diet_service_table_add(profile, NULL, solve_smprod);
  /* Free the profile descriptor, since it was deep copied. */
  diet_profile_desc_free(profile);

  /* Launch the SeD: no return call */
  diet_SeD("./SeD.cfg", argc, argv);

  /* Dead code */
  return 0;
}
\end{verbatim}
}

\section{Compilation}
\label{sec:sv_comp}

After compiling her/his server program, the user must link it with the DIET
and CORBA libraries. This process is very similar to the one described
for the client in section \ref{sec:cl_comp}. Please refer to this section
for details.
